{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们可以把RAG当作Agent可以调用的一个工具。\n",
    "\n",
    "先配置对话模型和嵌入模型。模型的构建可以参考wow-rag课程的第二课（https://github.com/datawhalechina/wow-rag/tree/main/tutorials），里面介绍了非常多配置对话模型和嵌入模型的方式。这里采用了本地Ollama的对话模型和嵌入模型。各种配置方式都可以，只要能有个能用的llm和embedding就行。\n",
    "\n",
    "如果运行还算顺利，可以顺便给wow-rag和wow-agent项目都点个小星星吗？谢谢！！！"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> ⚠️ 为了简化操作，依旧使用智谱 AI 的 glm-4-flash 和 embedding-3 ，请自行申请：https://www.bigmodel.cn/invite?icode=tzUaambCl5Rc0B964McaGGczbXFgPRGIalpycrEwJ28%3D"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 配置chat模型\n",
    "from llama_index.llms.zhipuai import ZhipuAI\n",
    "\n",
    "llm = ZhipuAI(model=\"glm-4-flash\", api_key=\"YOUR API KEY\")\n",
    "llm = ZhipuAI(model=\"glm-4-flash\", api_key=\"2ce2c9417f83dc0f582c00498b2bbd8b.374mpCJDIXF5ksmq\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 配置Embedding模型\n",
    "from llama_index.embeddings.zhipuai import ZhipuAIEmbedding\n",
    "\n",
    "embedding = ZhipuAIEmbedding(model=\"embedding-3\", api_key=\"YOUR API KEY\")\n",
    "embedding = ZhipuAIEmbedding(model=\"embedding-3\", api_key=\"2ce2c9417f83dc0f582c00498b2bbd8b.374mpCJDIXF5ksmq\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "上边这个llm和embedding有很多方法可以构建。详情参见wow-rag的第二课。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "我是一个名为 ChatGLM 的人工智能助手，是基于清华大学 KEG 实验室和智谱 AI 公司于 2024 年共同训练的语言模型开发的。我的任务是针对用户的问题和要求提供适当的答复和支持。\n"
     ]
    }
   ],
   "source": [
    "# 测试对话模型\n",
    "response = llm.complete(\"你是谁？\")\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1024, list)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 测试嵌入模型\n",
    "emb = embedding.get_text_embedding(\"你是谁？\")\n",
    "len(emb), type(emb)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "输出 (1024, list)\n",
    "\n",
    "说明配置成功。\n",
    "\n",
    "\n",
    "\n",
    "然后构建索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Defaulting to user installation because normal site-packages is not writeable\n",
      "Looking in indexes: https://mirrors.aliyun.com/pypi/simple\n",
      "Collecting faiss-cpu\n",
      "  Downloading https://mirrors.aliyun.com/pypi/packages/d6/39/298ffcbefd899e84a43e63df217a6dc800d52bca37ebe0d1155ff367886a/faiss_cpu-1.10.0-cp310-cp310-win_amd64.whl (13.7 MB)\n",
      "     ---------------------------------------- 0.0/13.7 MB ? eta -:--:--\n",
      "     --- ------------------------------------ 1.0/13.7 MB 5.6 MB/s eta 0:00:03\n",
      "     ------ --------------------------------- 2.4/13.7 MB 5.6 MB/s eta 0:00:03\n",
      "     ---------- ----------------------------- 3.7/13.7 MB 5.7 MB/s eta 0:00:02\n",
      "     ------------- -------------------------- 4.7/13.7 MB 5.6 MB/s eta 0:00:02\n",
      "     ----------------- ---------------------- 6.0/13.7 MB 5.6 MB/s eta 0:00:02\n",
      "     --------------------- ------------------ 7.3/13.7 MB 5.6 MB/s eta 0:00:02\n",
      "     ------------------------- -------------- 8.7/13.7 MB 5.6 MB/s eta 0:00:01\n",
      "     ----------------------------- ---------- 10.0/13.7 MB 5.6 MB/s eta 0:00:01\n",
      "     -------------------------------- ------- 11.0/13.7 MB 5.6 MB/s eta 0:00:01\n",
      "     ------------------------------------ --- 12.3/13.7 MB 5.6 MB/s eta 0:00:01\n",
      "     ---------------------------------------  13.4/13.7 MB 5.6 MB/s eta 0:00:01\n",
      "     ---------------------------------------- 13.7/13.7 MB 5.4 MB/s eta 0:00:00\n",
      "Requirement already satisfied: numpy<3.0,>=1.25.0 in c:\\programdata\\miniconda3\\envs\\dbgpt_env\\lib\\site-packages (from faiss-cpu) (1.26.4)\n",
      "Requirement already satisfied: packaging in c:\\programdata\\miniconda3\\envs\\dbgpt_env\\lib\\site-packages (from faiss-cpu) (24.2)\n",
      "Installing collected packages: faiss-cpu\n",
      "Successfully installed faiss-cpu-1.10.0\n",
      "Note: you may need to restart the kernel to use updated packages.\n"
     ]
    }
   ],
   "source": [
    "pip install faiss-cpu -i https://mirrors.aliyun.com/pypi/simple"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 从指定文件读取，输入为List\n",
    "from llama_index.core import SimpleDirectoryReader,Document\n",
    "documents = SimpleDirectoryReader(input_files=['../docs/问答手册.txt', '../docs/商标注册.txt']).load_data()\n",
    "\n",
    "# 构建节点\n",
    "from llama_index.core.node_parser import SentenceSplitter\n",
    "transformations = [SentenceSplitter(chunk_size = 512)]\n",
    "\n",
    "from llama_index.core.ingestion.pipeline import run_transformations\n",
    "nodes = run_transformations(documents, transformations=transformations)\n",
    "\n",
    "# 构建索引\n",
    "from llama_index.vector_stores.faiss import FaissVectorStore\n",
    "import faiss\n",
    "from llama_index.core import StorageContext, VectorStoreIndex\n",
    "\n",
    "emb = embedding.get_text_embedding(\"你好呀呀\")\n",
    "vector_store = FaissVectorStore(faiss_index=faiss.IndexFlatL2(len(emb)))\n",
    "storage_context = StorageContext.from_defaults(vector_store=vector_store)\n",
    "\n",
    "index = VectorStoreIndex(\n",
    "    nodes = nodes,\n",
    "    storage_context=storage_context,\n",
    "    embed_model = embedding,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "然后构建问答引擎"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 构建检索器\n",
    "from llama_index.core.retrievers import VectorIndexRetriever\n",
    "# 想要自定义参数，可以构造参数字典\n",
    "kwargs = {'similarity_top_k': 5, 'index': index, 'dimensions': len(emb)} # 必要参数\n",
    "retriever = VectorIndexRetriever(**kwargs)\n",
    "\n",
    "# 构建合成器\n",
    "from llama_index.core.response_synthesizers  import get_response_synthesizer\n",
    "response_synthesizer = get_response_synthesizer(llm=llm, streaming=True)\n",
    "\n",
    "# 构建问答引擎\n",
    "from llama_index.core.query_engine import RetrieverQueryEngine\n",
    "engine = RetrieverQueryEngine(\n",
    "      retriever=retriever,\n",
    "      response_synthesizer=response_synthesizer,\n",
    "        )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "用RAG回答一下试试效果："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Agent AI systems can be applied in interactive AI, content generation for bots and AI agents, productivity applications such as content replay, paraphrasing, action prediction, and synthesis of 3D or 2D scenarios. These systems also have potential applications in health topics, including ethical deployment in sensitive domains like healthcare. They can transform the gaming industry by shifting developer focus and refine agent learning processes, as well as redefine manufacturing roles with adaptive robotic systems."
     ]
    }
   ],
   "source": [
    "# 提问\n",
    "question = \"What are the applications of Agent AI systems ?\"\n",
    "response = engine.query(question)\n",
    "for text in response.response_gen:\n",
    "    print(text, end=\"\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "理想输出\n",
    "\n",
    "```\n",
    "Agent AI systems have a variety of applications, which include:\n",
    "\n",
    "1. Interactive AI: Enhancing user interactions and providing personalized experiences.\n",
    "2. Content Generation: Assisting in the creation of content for bots and AI agents, which can be used in various applications such as customer service or storytelling.\n",
    "3. Productivity: Improving productivity in applications by enabling tasks like replaying events, paraphrasing information, predicting actions, and synthesizing scenarios (both 3D and 2D).\n",
    "4. Healthcare: Ethical deployment in sensitive domains like healthcare, which could potentially improve diagnoses and patient care while also addressing health disparities.\n",
    "5. Gaming Industry: Transforming the role of developers by shifting focus from scripting non-player characters to refining agent learning processes.\n",
    "6. Robotics and Manufacturing: Redefining manufacturing roles and requiring new skill sets, rather than replacing human workers, as adaptive robotic systems are developed.\n",
    "7. Simulation: Learning collaboration policies within simulated environments, which can be applied to the real world with careful consideration and safety measures.\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们可以把这个RAG当作一个工具给Agent调用，让它去思考。\n",
    "先来配置问答工具"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 配置查询工具\n",
    "from llama_index.core.tools import QueryEngineTool\n",
    "from llama_index.core.tools import ToolMetadata\n",
    "query_engine_tools = [\n",
    "    QueryEngineTool(\n",
    "        query_engine=engine,\n",
    "        metadata=ToolMetadata(\n",
    "            name=\"RAG工具\",\n",
    "            description=(\n",
    "                \"用于在原文中检索相关信息\"\n",
    "            ),\n",
    "        ),\n",
    "    ),\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "创建ReAct Agent"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建ReAct Agent\n",
    "from llama_index.core.agent import ReActAgent\n",
    "agent = ReActAgent.from_tools(query_engine_tools, llm=llm, verbose=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "调用Agent"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "> Running step 96208f24-d453-47c8-8085-b19d6d148559. Step input: 请问商标注册需要提供哪些文件？\n",
      "\u001b[1;3;38;5;200mThought: The user is asking about the documents required for trademark registration. I need to use a tool to help me answer this question.\n",
      "Action: RAG工具\n",
      "Action Input: {'input': '商标注册需要提供哪些文件？'}\n",
      "\u001b[0m\u001b[1;3;34mObservation: 商标注册需要提供的文件通常包括但不限于以下内容：\n",
      "\n",
      "1. 商标注册申请书：填写商标注册申请的相关信息，包括申请人信息、商标图样、商品或服务类别等。\n",
      "2. 申请人身份证明文件：如个人身份证、企业营业执照等。\n",
      "3. 商标图样：清晰、准确的商标图样，可以是黑白或彩色，但必须是清晰可辨的。\n",
      "4. 商品或服务列表：详细列出商标所适用的商品或服务类别，需按照《商标注册用商品和服务国际分类》进行分类。\n",
      "5. 商标代理委托书：如委托代理人办理商标注册事宜，需提供委托书，并附上代理人身份证明文件。\n",
      "6. 其他相关文件：根据具体情况，可能还需要提供其他文件，如变更申请、续展申请等。\n",
      "\n",
      "请注意，具体所需文件可能因国家或地区而异，建议咨询当地商标注册机构或专业律师。\n",
      "\u001b[0m> Running step 990d9d6e-d285-48dc-aa15-ad35a7035513. Step input: None\n",
      "\u001b[1;3;38;5;200mThought: I can answer without using any more tools. I'll use the user's language to answer\n",
      "Answer: 商标注册需要提供的文件通常包括但不限于以下内容：商标注册申请书、申请人身份证明文件、商标图样、商品或服务列表、商标代理委托书以及可能的其他相关文件。具体所需文件可能因国家或地区而异，建议咨询当地商标注册机构或专业律师。\n",
      "\u001b[0m商标注册需要提供的文件通常包括但不限于以下内容：商标注册申请书、申请人身份证明文件、商标图样、商品或服务列表、商标代理委托书以及可能的其他相关文件。具体所需文件可能因国家或地区而异，建议咨询当地商标注册机构或专业律师。\n"
     ]
    }
   ],
   "source": [
    "# 让Agent完成任务\n",
    "response = agent.chat(\"请问商标注册需要提供哪些文件？\")\n",
    "# response = agent.chat(\"What are the applications of Agent AI systems ?\")\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "理想输出:\n",
    "```\n",
    "Thought: 我需要使用工具来获取关于商标注册所需文件的信息。\n",
    "Action: RAG\n",
    "Action Input: {'input': '商标注册需要提供哪些文件'}\n",
    "Observation: 商标注册通常需要以下文件：\n",
    "\n",
    "1. **企业**：申请人为企业的，则需提供：\n",
    "   - 营业执照复印件\n",
    "   - 授权委托书（如果由代理人提交）\n",
    "   - 商标图案电子档\n",
    "   - 具体商品或服务的名称\n",
    "\n",
    "2. **国内自然人**：以个人名义申请时，需要提供：\n",
    "   - 个体工商户档案（如有营业执照）\n",
    "   - 自然人身份证复印件\n",
    "   - 授权委托书（如果由代理人提交）\n",
    "   - 商标图案电子档\n",
    "   - 具体商品或服务的名称\n",
    "\n",
    "3. **国外自然人**：申请商标时，通常需要：\n",
    "   - 护照复印件（作为身份证明文件）\n",
    "   - 授权委托书（如果由代理人提交）\n",
    "   - 商标图案电子档\n",
    "   - 具体商品或服务的名称\n",
    "\n",
    "请注意，具体要求可能会因国家和地区政策的不同而有所变化。在实际申请前，请咨询当地的知识产权局或专业代理机构以获取最准确的信息。\n",
    "Thought: 我可以使用这些信息来回答问题。\n",
    "Answer: 商标注册通常需要以下文件：\n",
    "\n",
    "1. **企业**：营业执照复印件、授权委托书（如果由代理人提交）、商标图案电子档以及具体商品或服务的名称。\n",
    "2. **国内自然人**：个体工商户档案（如有）、自然人身份证复印件、授权委托书（如果由代理人提交）、商标图案电子档和具体商品或服务的名称。\n",
    "3. **国外自然人**：护照复印件作为身份证明文件、授权委托书（如果由代理人提交）、商标图案电子档以及具体商品或服务的名称。\n",
    "\n",
    "请注意，具体的申请要求可能会因国家和地区政策的不同而有所变化。在实际申请前，请咨询当地的知识产权局或专业代理机构以获取最准确的信息。\n",
    "商标注册通常需要以下文件：\n",
    "\n",
    "1. **企业**：营业执照复印件、授权委托书（如果由代理人提交）、商标图案电子档以及具体商品或服务的名称。\n",
    "2. **国内自然人**：个体工商户档案（如有）、自然人身份证复印件、授权委托书（如果由代理人提交）、商标图案电子档和具体商品或服务的名称。\n",
    "3. **国外自然人**：护照复印件作为身份证明文件、授权委托书（如果由代理人提交）、商标图案电子档以及具体商品或服务的名称。\n",
    "\n",
    "请注意，具体的申请要求可能会因国家和地区政策的不同而有所变化。在实际申请前，请咨询当地的知识产权局或专业代理机构以获取最准确的信息。\n",
    "````"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "看起来这个回答比单纯使用RAG的效果好很多。\n",
    "⚠️效果依赖于大模型的能力，如果大模型能力不足，那么效果可能还不如RAG。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "dbgpt_env",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
